home *** CD-ROM | disk | FTP | other *** search
- {$I DFS.INC} { Standard defines for all Delphi Free Stuff components }
-
- {-----------------------------------------------------------------------------}
- { TDFSColorButton v1.80 }
- {-----------------------------------------------------------------------------}
- { A Windows 95 and NT 4 style color selection button. It displays a palette }
- { of 20 color for fast selction and a button to bring up the color dialog. }
- { Copyright 1996, Brad Stowers. All Rights Reserved. }
- { This component can be freely used and distributed in commercial and private }
- { environments, provied this notice is not modified in any way and there is }
- { no charge for it other than nomial handling fees. Contact me directly for }
- { modifications to this agreement. }
- {-----------------------------------------------------------------------------}
- { Feel free to contact me if you have any questions, comments or suggestions }
- { at bstowers@pobox.com. }
- { The lateset version will always be available on the web at: }
- { http://www.pobox.com/~bstowers/delphi/ }
- { See ColorBtn.txt for notes, known issues, and revision history. }
- {-----------------------------------------------------------------------------}
- { Date last modified: February 5, 1997 }
- {-----------------------------------------------------------------------------}
-
- unit DFSClrBn;
-
- interface
-
- {$IFDEF DFS_WIN32}
- {$R DFSClrBn.res}
- {$ELSE}
- {$R DFSClrBn.r16}
- {$ENDIF}
-
- uses
- WinTypes, WinProcs, Messages, Classes, Controls, Forms, Graphics, StdCtrls,
- Buttons, ExtCtrls, CBtnForm;
-
- type
- TDFSColorButton = class(TButton)
- private
- FPaletteForm: TDFSColorButtonPalette;
- FSectionName: string;
- FOtherBtnCaption: string;
- FColorsLoaded: boolean;
- FCanvas: TCanvas;
- IsFocused: boolean;
- FStyle: TButtonStyle;
- FColor: TColor;
- FPaletteDisplayed: boolean;
- FPaletteColors: TPaletteColors;
- FOtherColor: TColor;
- FCustomColors: TCustomColors;
- {$IFDEF DFS_WIN32}
- FFlat: boolean;
- FCustomColorsKey: string;
- {$ELSE}
- FCustomColorsINI: string;
- {$ENDIF}
- FOnColorChange: TNotifyEvent;
- FArrowBmp: TBitmap;
- FIsMouseOver: boolean;
-
- procedure CNMeasureItem(var Msg: TWMMeasureItem); message CN_MEASUREITEM;
- procedure CNDrawItem(var Msg: TWMDrawItem); message CN_DRAWITEM;
- procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
- procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
- procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
- {$IFDEF DFS_WIN32}
- procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
- procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
- {$ENDIF}
-
- procedure SetStyle(Value: TButtonStyle);
- procedure SetColor(Value: TColor);
- procedure SetPaletteColors(Value: TPaletteColors);
- procedure SetCustomColors(Value: TCustomColors);
- procedure SetArrowBmp(Value: TBitmap);
- {$IFDEF DFS_WIN32}
- procedure SetFlat(Value: boolean);
- {$ENDIF}
-
- procedure DrawItem(const DrawItemStruct: TDrawItemStruct);
- procedure PaletteSetColor(Sender: TObject; AColor: TColor);
- procedure PaletteClosed(Sender: TObject);
- protected
- procedure CreateParams(var Params: TCreateParams); override;
- procedure CreateWnd; override;
- procedure Loaded; override;
- procedure SetButtonStyle(ADefault: Boolean); override;
- procedure SetDefaultColors; virtual;
-
- function GetSectionName: string; virtual;
- procedure SaveCustomColors; virtual;
- procedure LoadCustomColors; virtual;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Click; override;
- procedure DoColorChange; virtual;
- property ArrowBmp: TBitmap read FArrowBmp write SetArrowBmp;
- published
- property Style: TButtonStyle
- read FStyle
- write SetStyle
- default bsAutoDetect;
- property Color: TColor
- read FColor
- write SetColor
- default clBlack;
- property OtherBtnCaption: string
- read FOtherBtnCaption
- write FOtherBtnCaption;
- property OtherColor: TColor
- read FOtherColor
- write FOtherColor;
- property PaletteColors: TPaletteColors
- read FPaletteColors
- write SetPaletteColors
- stored TRUE;
- property CustomColors: TCustomColors
- read FCustomColors
- write SetCustomColors
- stored TRUE;
- {$IFDEF DFS_WIN32}
- property Flat: boolean
- read FFlat
- write SetFlat
- default FALSE;
- property CustomColorsKey: string
- read FCustomColorsKey
- write FCustomColorsKey;
- {$ELSE}
- property CustomColorsINI: string
- read FCustomColorsINI
- write FCustomColorsINI;
- {$ENDIF}
- property OnColorChange: TNotifyEvent
- read FOnColorChange
- write FOnColorChange;
- end;
-
- procedure Register;
-
- implementation
-
- uses
- ColorAEd, SysUtils,
- {$IFDEF DFS_WIN32}
- Registry,
- {$ELSE}
- IniFiles,
- {$ENDIF}
- DsgnIntf;
-
- procedure Register;
- begin
- RegisterComponents('Delphi Free Stuff', [TDFSColorButton]);
- RegisterPropertyEditor(TypeInfo(TColorArrayClass), NIL, '',
- TColorArrayProperty);
- end;
-
-
- constructor TDFSColorButton.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FArrowBmp := TBitmap.Create;
- FArrowBmp.Handle := LoadBitmap(HInstance, 'DFS_ARROW_BMP');
- FPaletteColors := TColorArrayClass.Create(4,5);
- FCustomColors := TColorArrayClass.Create(8,2);
- FPaletteForm := NIL;
- FOtherBtnCaption := '&Other';
- FColorsLoaded := FALSE;
- FCanvas := TCanvas.Create;
- FStyle := bsAutoDetect;
- FColor := clBlack;
- FPaletteDisplayed := FALSE;
- Caption := '';
- FIsMouseOver := FALSE;
- {$IFDEF DFS_DELPHI_3}
- ControlStyle := ControlStyle + [csReflector];
- {$ENDIF}
- {$IFDEF DFS_WIN32}
- FFlat := FALSE;
- FCustomColorsKey := '';
- {$ELSE}
- FCustomColorsINI := '';
- {$ENDIF}
- SetDefaultColors;
- Width := 45;
- Height := 22;
- end;
-
- destructor TDFSColorButton.Destroy;
- begin
- SaveCustomColors;
- FCanvas.Free;
- FPaletteColors.Free;
- FCustomColors.Free;
- FArrowBmp.Free;
- inherited Destroy;
- end;
-
- procedure TDFSColorButton.CreateWnd;
- begin
- inherited CreateWnd;
-
- if not FColorsLoaded then
- LoadCustomColors;
- end;
-
-
- procedure TDFSColorButton.Loaded;
- begin
- inherited Loaded;
-
- LoadCustomColors;
- end;
-
-
- procedure TDFSColorButton.CreateParams(var Params: TCreateParams);
- begin
- inherited CreateParams(Params);
- Params.Style := Params.Style OR BS_OWNERDRAW;
- end;
-
- procedure TDFSColorButton.SetStyle(Value: TButtonStyle);
- begin
- if Value <> FStyle then
- begin
- FStyle := Value;
- Invalidate;
- end;
- end;
-
- procedure TDFSColorButton.SetColor(Value: TColor);
- begin
- if Value <> FColor then
- begin
- FColor := Value;
- Invalidate;
- DoColorChange;
- end;
- end;
-
- procedure TDFSColorButton.CNMeasureItem(var Msg: TWMMeasureItem);
- begin
- with Msg.MeasureItemStruct^ do
- begin
- itemWidth := Width;
- itemHeight := Height;
- end;
- Msg.Result := 1;
- end;
-
- procedure TDFSColorButton.CNDrawItem(var Msg: TWMDrawItem);
- begin
- DrawItem(Msg.DrawItemStruct^);
- Msg.Result := 1;
- end;
-
- procedure TDFSColorButton.DrawItem(const DrawItemStruct: TDrawItemStruct);
- var
- IsDown, IsDefault: Boolean;
- R: TRect;
- Flags: Longint;
- CursorPos: TPoint;
- BtnRect: TRect;
- {$IFNDEF DFS_WIN32}
- NewStyle: boolean;
- Bevel: integer;
- TextBounds: TRect;
- {$ENDIF}
- begin
- FCanvas.Handle := DrawItemStruct.hDC;
- try
- R := ClientRect;
-
- with DrawItemStruct do
- begin
- IsDown := (itemState and ODS_SELECTED <> 0) or (FPaletteDisplayed);
- IsDefault := itemState and ODS_FOCUS <> 0;
- end;
-
- GetCursorPos(CursorPos);
- BtnRect.TopLeft := Parent.ClientToScreen(Point(Left, Top));
- BtnRect.BottomRight := Parent.ClientToScreen(Point(Left + Width,
- Top + Height));
- FIsMouseOver := PtInRect(BtnRect, CursorPos);
-
- {$IFDEF DFS_WIN32}
- Flags := DFCS_BUTTONPUSH or DFCS_ADJUSTRECT;
- if IsDown then Flags := Flags or DFCS_PUSHED;
- if DrawItemStruct.itemState and ODS_DISABLED <> 0 then
- Flags := Flags or DFCS_INACTIVE;
- { Don't draw flat if mouse is over it or has the input focus }
- if FFlat and (not FIsMouseOver) and (not Focused) then
- Flags := Flags or DFCS_FLAT;
-
- if IsDown then
- begin
- FCanvas.Pen.Color := clWindowFrame;
- FCanvas.Pen.Width := 1;
- FCanvas.Brush.Style := bsClear;
- FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
-
- { DrawFrameControl must draw within this border }
- InflateRect(R, -1, -1);
- end;
-
- { DrawFrameControl does not draw a pressed button correctly }
- if IsDown then
- begin
- FCanvas.Pen.Color := clBtnShadow;
- FCanvas.Pen.Width := 1;
- FCanvas.Brush.Color := clBtnFace;
- FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
- InflateRect(R, -1, -1);
- end else begin
- DrawFrameControl(DrawItemStruct.hDC, R, DFC_BUTTON, Flags);
- if (Flags and DFCS_FLAT) <> 0 then
- begin
- { I don't know why, but it insists on drawing this little rectangle }
- InflateRect(R, 2, 2);
- FCanvas.Brush.Color := clBtnFace;
- FCanvas.FrameRect(R);
- InflateRect(R, -2, -2);
- end;
- end;
-
- if IsFocused then
- begin
- R := ClientRect;
- InflateRect(R, -1, -1);
- end;
-
- R := ClientRect;
-
- if IsDown then
- OffsetRect(R, 1, 1);
-
- InflateRect(R, -3, -3);
- if IsFocused and IsDefault then
- begin
- FCanvas.Pen.Color := clWindowFrame;
- FCanvas.Brush.Color := clBtnFace;
- DrawFocusRect(FCanvas.Handle, R);
- end;
-
- {$ELSE}
-
- NewStyle := ((Style = bsAutoDetect) and NewStyleControls) or (Style = bsNew);
-
- if NewStyle then Bevel := 1
- else Bevel := 2;
-
- R := DrawButtonFace(FCanvas, ClientRect, Bevel, FStyle, not NewStyle,
- IsDown, IsDefault or IsFocused);
-
- if IsDefault then
- begin
- FCanvas.Brush.Color := clBtnFace;
- TextBounds := R;
- if NewStyle then
- begin
- InflateRect(TextBounds, -2, -2);
- if IsDown then OffsetRect(TextBounds, -1, -1);
- end
- else InflateRect(TextBounds, 1, 1);
- DrawFocusRect(FCanvas.Handle, TextBounds);
- end;
- InflateRect(R, -3, -3);
-
- {$ENDIF}
-
- { Draw the color rect }
- InflateRect(R, -2, -1);
- Dec(R.Right, 10);
- FCanvas.Pen.Color := clWindowFrame;
- FCanvas.Pen.Width := 1;
- FCanvas.Brush.Style := bsClear;
- FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
- FCanvas.Brush.Color := FColor;
- FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
-
- { Draw divider line }
- R.Left := R.Right + 3;
- FCanvas.Pen.Color := clBtnShadow;
- FCanvas.MoveTo(R.Left, R.Top);
- FCanvas.LineTo(R.Left, R.Bottom);
- inc(R.Left);
- FCanvas.Pen.Color := clBtnHighlight;
- FCanvas.MoveTo(R.Left, R.Top);
- FCanvas.LineTo(R.Left, R.Bottom);
-
- { Draw the arrow }
- inc(R.Left, 1);
- inc(R.Top, ((R.Bottom - R.Top) div 2) - (FArrowBmp.Height div 2));
- R.Right := R.Left + FArrowBmp.Width-1;
- R.Bottom := R.Top + FArrowBmp.Height-1;
- FCanvas.Brush.Color := clBtnFace;
- FCanvas.BrushCopy(R, FArrowBmp, Rect(0, 0, FArrowBmp.Width-1,
- FArrowBmp.Height-1), FArrowBmp.Canvas.Pixels[0, FArrowBmp.Height-1]);
- finally
- FCanvas.Handle := 0;
- end;
- end;
-
- procedure TDFSColorButton.CMFontChanged(var Message: TMessage);
- begin
- inherited;
- Invalidate;
- end;
-
- procedure TDFSColorButton.CMEnabledChanged(var Message: TMessage);
- begin
- inherited;
- Invalidate;
- end;
-
- procedure TDFSColorButton.WMLButtonDblClk(var Message: TWMLButtonDblClk);
- begin
- Perform(WM_LBUTTONDOWN, Message.Keys, Longint(Message.Pos));
- end;
-
- procedure TDFSColorButton.SetButtonStyle(ADefault: Boolean);
- begin
- if ADefault <> IsFocused then
- begin
- IsFocused := ADefault;
- Refresh;
- end;
- end;
-
- procedure TDFSColorButton.Click;
- var
- PalXY: TPoint;
- {$IFDEF DFS_WIN32}
- ScreenRect: TRect;
- {$ENDIF}
- begin
- {$IFDEF DFS_DELPHI_3}
- Application.NormalizeAllTopMosts;
- {$ELSE}
- Application.NormalizeTopMosts;
- {$ENDIF}
-
- FPaletteForm := TDFSColorButtonPalette.Create(Self);
- PalXY := Parent.ClientToScreen(Point(Left, Top + Height));
- {$IFDEF DFS_WIN32}
- { Screen.Width and Height don't account for non-hidden task bar. }
- SystemParametersInfo(SPI_GETWORKAREA, 0, @ScreenRect, 0);
- if PalXY.Y + 121 > ScreenRect.Bottom then
- { No room to display below the button, show it above instead }
- PalXY := Parent.ClientToScreen(Point(Left, Top - 121));
- if PalXY.X < ScreenRect.Left then
- { No room to display horizontally, shift right }
- PalXY.X := ScreenRect.Left
- else if PalXY.X + 78 > ScreenRect.Right then
- { No room to display horizontally, shift left }
- PalXY.X := ScreenRect.Right - 78;
- FPaletteForm.SetBounds(PalXY.X, PalXY.Y, 78, 121);
- {$ELSE}
- if PalXY.Y + 121 > Screen.Height then
- { No room to display below the button, show it above instead }
- PalXY := Parent.ClientToScreen(Point(Left, Top - 121));
- if PalXY.X < 0 then
- { No room to display horizontally, shift right }
- PalXY.X := 0
- else if PalXY.X + 78 > Screen.Width then
- { No room to display horizontally, shift left }
- PalXY.X := Screen.Width - 78;
- FPaletteForm.SetBounds(PalXY.X, PalXY.Y, 78, 121);
- {$ENDIF}
- FPaletteForm.btnOther.Caption := OtherBtnCaption;
- FPaletteForm.OtherColor := OtherColor;
- FPaletteForm.Color := Color;
- FPaletteForm.SetParentColor := PaletteSetColor;
- FPaletteForm.PaletteClosed := PaletteClosed;
- FPaletteForm.PaletteColors := PaletteColors;
- FPaletteForm.CustomColors := CustomColors;
- FPaletteDisplayed := TRUE;
- Refresh;
- FPaletteForm.Show;
- end;
-
- procedure TDFSColorButton.PaletteSetColor(Sender: TObject; AColor: TColor);
- begin
- Color := AColor;
- end;
-
- procedure TDFSColorButton.PaletteClosed(Sender: TObject);
- begin
- if FPaletteForm = NIL then exit;
- CustomColors := FPaletteForm.CustomColors;
- FPaletteDisplayed := FALSE;
- Invalidate;
- FPaletteForm := NIL;
- Application.RestoreTopMosts;
- end;
-
- procedure TDFSColorButton.SetPaletteColors(Value: TPaletteColors);
- begin
- FPaletteColors.Assign(Value);
- end;
-
- procedure TDFSColorButton.SetCustomColors(Value: TCustomColors);
- begin
- FCustomColors.Assign(Value);
- end;
-
-
- function ColorEnumProc(Pen: PLogPen; var Colors: array of TColorRef): integer;
- {$IFDEF DFS_WIN32} stdcall; {$ELSE} export; {$ENDIF}
- begin
- if Pen^.lopnStyle = PS_SOLID then
- begin
- if Colors[0] < 20 then
- begin
- inc(Colors[0]);
- Colors[Colors[0]] := Pen^.lopnColor;
- Result := 1;
- end else
- Result := 0;
- end else
- Result := 1;
- end;
-
-
- procedure TDFSColorButton.SetDefaultColors;
- var
- X, Y: integer;
- DefColors: array[0..20] of TColorRef;
- DC: HDC;
- begin
- DC := GetDC(GetDesktopWindow);
- try
- if GetDeviceCaps(DC, NUMCOLORS) = 16 then
- begin
- { 16 color mode, enum colors to fill array }
- FillChar(DefColors, SizeOf(DefColors), #0);
- EnumObjects(DC, OBJ_PEN, @ColorEnumProc,
- {$IFDEF DFS_WIN32} LPARAM(@DefColors) {$ELSE} @DefColors {$ENDIF});
- for X := 1 to 4 do
- begin
- for Y := 1 to 5 do
- begin
- PaletteColors[X,Y] := DefColors[(X-1)*5+Y];
- end;
- end;
- end else begin
- { Lots 'o colors, pick the ones we want. }
- PaletteColors[1,1] := RGB(255,255,255);
- PaletteColors[1,2] := RGB(255,0,0);
- PaletteColors[1,3] := RGB(0,255,0);
- PaletteColors[1,4] := RGB(0,0,255);
- PaletteColors[1,5] := RGB(191,215,191);
- PaletteColors[2,1] := RGB(0,0,0);
- PaletteColors[2,2] := RGB(127,0,0);
- PaletteColors[2,3] := RGB(0,127,0);
- PaletteColors[2,4] := RGB(0,0,127);
- PaletteColors[2,5] := RGB(159,191,239);
- PaletteColors[3,1] := RGB(191,191,191);
- PaletteColors[3,2] := RGB(255,255,0);
- PaletteColors[3,3] := RGB(0,255,255);
- PaletteColors[3,4] := RGB(255,0,255);
- PaletteColors[3,5] := RGB(255,247,239);
- PaletteColors[4,1] := RGB(127,127,127);
- PaletteColors[4,2] := RGB(127,127,0);
- PaletteColors[4,3] := RGB(0,127,127);
- PaletteColors[4,4] := RGB(127,0,127);
- PaletteColors[4,5] := RGB(159,159,159);
- end;
- finally
- ReleaseDC(GetDesktopWindow, DC);
- end;
-
- for x := 1 to 8 do
- for y := 1 to 2 do
- CustomColors[x,y] := clWhite;
-
- FOtherColor := clBtnFace;
- end;
-
-
- function TDFSColorButton.GetSectionName: string;
- begin
- Result := Self.Name;
- if Parent <> NIL then
- Result := Parent.Name + '.' + Result;
- end;
-
-
- procedure TDFSColorButton.SaveCustomColors;
- var
- {$IFDEF DFS_WIN32}
- Reg: TRegIniFile;
- {$ELSE}
- Ini: TIniFile;
- {$ENDIF}
- Colors: string;
- x: integer;
- y: integer;
- begin
- Colors := '';
- for x := 1 to 8 do
- begin
- for y := 1 to 2 do
- begin
- Colors := Colors + '$' + IntToHex(CustomColors[x,y], 8) + ',';
- end;
- end;
- Delete(Colors, Length(Colors), 1); { strip last comma }
-
- {$IFDEF DFS_WIN32}
- if FCustomColorsKey <> '' then
- begin
- Reg := TRegIniFile.Create(FCustomColorsKey);
- try
- Reg.WriteString('Colors', FSectionName, Colors);
- finally
- Reg.Free;
- end;
- end;
- {$ELSE}
- if FCustomColorsINI <> '' then
- begin
- Ini := TIniFile.Create(FCustomColorsINI);
- try
- Ini.WriteString('Colors', FSectionName, Colors);
- finally
- Ini.Free;
- end;
- end;
- {$ENDIF}
- end;
-
-
- procedure TDFSColorButton.LoadCustomColors;
- var
- {$IFDEF DFS_WIN32}
- Reg: TRegIniFile;
- {$ELSE}
- Ini: TIniFile;
- {$ENDIF}
- Colors: string;
- AColor: string;
- CPos: byte;
- x: integer;
- y: integer;
- begin
- Colors := '';
- FSectionName := GetSectionName;
- FColorsLoaded := TRUE;
-
- {$IFDEF DFS_WIN32}
- if FCustomColorsKey <> '' then
- begin
- Reg := TRegIniFile.Create(FCustomColorsKey);
- try
- Colors := Reg.ReadString('Colors', FSectionName, '');
- finally
- Reg.Free;
- end;
- {$ELSE}
- if FCustomColorsINI <> '' then
- begin
- Ini := TIniFile.Create(FCustomColorsINI);
- try
- Colors := Ini.ReadString('Colors', FSectionName, '');
- finally
- Ini.Free;
- end;
- {$ENDIF}
- if Colors <> '' then
- begin
- x := 1;
- y := 1;
- CPos := Pos(',', Colors);
- while CPos > 0 do
- begin
- AColor := Copy(Colors, 1, CPos-1);
- CustomColors[x,y] := StrToIntDef(AColor, clWhite);
- inc(y);
- if y > 2 then
- begin
- y := 1;
- inc(x);
- if x > 8 then
- break; { all done }
- end;
- Colors := Copy(Colors, CPos+1, Length(Colors));
- end; { while }
- end;
- end;
- end;
-
-
- procedure TDFSColorButton.DoColorChange;
- begin
- if assigned(FOnColorChange) then
- FOnColorChange(Self);
- end;
-
- procedure TDFSColorButton.SetArrowBmp(Value: TBitmap);
- begin
- if Value <> NIL then
- begin
- FArrowBmp.Assign(Value);
- Invalidate;
- end;
- end;
-
- {$IFDEF DFS_WIN32}
- procedure TDFSColorButton.SetFlat(Value: boolean);
- begin
- if Value <> FFlat then
- begin
- FFlat := Value;
- Invalidate;
- end;
- end;
-
- procedure TDFSColorButton.CMMouseEnter(var Message: TMessage);
- begin
- if FFlat and (not FIsMouseOver) then
- Invalidate;
- end;
-
- procedure TDFSColorButton.CMMouseLeave(var Message: TMessage);
- begin
- if FFlat and (FIsMouseOver) then
- Invalidate;
- end;
- {$ENDIF}
-
-
- end.
-
-
-